package com.load.loaders.imp;

import static com.load.parsers.ClassParser.*;
import japa.parser.ParseException;
import japa.parser.ast.CompilationUnit;

import org.apache.log4j.Logger;
import org.tmatesoft.svn.core.io.SVNRepository;

import com.database.daos.IElementDao;
import com.database.objects.*;
import com.database.objects.Class;
import com.load.batch.BatchExecutor;
import com.load.loaders.ILoader;

public class LoaderFile implements ILoader {

	private static Logger logger = Logger.getLogger("load.repository");

	private IElementDao elementDao;

	private LoaderClass loaderClass;

	@Override
	public void loadChilds(SVNRepository svnRepository, Type type, Element<?, ?> element, BatchExecutor executor) {
		File file = (File) element;
		if (file.isFile()) {
			checkAddFile(svnRepository, file);
			checkModifyFile(svnRepository, file);
			checkDeleteFile(svnRepository, file);

			int index = 1;
			for (Class clazz : file.getChilds()) {
				elementDao.saveElement(clazz);
				if (file.isFileOO() && type.impliesMethod()) {
					logger.info("CLASS: " + index + " - " + clazz.getName());
					loaderClass.loadChilds(svnRepository, type, clazz, executor);
					index++;
				}
			}
		}
	}

	private void checkAddFile(SVNRepository svnRepository, File file) {
		if (file.isAddStatus()) {
			if (file.isFileOO()) {
				try {
					logger.info("FILE OO: " + file.getPath() + " - STATUS: added");
					FileOO fileOO = (FileOO) file;
					CompilationUnit compilation = fileOO.buildCompilation();
					addClasses(compilation, fileOO);
					logger.info("FILE OO: " + file.getPath() + " - " + fileOO.getNumberChilds() + " classes");
				} catch (ParseException e) {
					e.printStackTrace();
					logger.error("ERROR: Obtaining compilation unit of file " + file.getPath());
				}
			} else {
				logger.info("FILE NO OO: " + file.getPath() + " - STATUS: added");
			}
		}
	}

	private void checkModifyFile(SVNRepository svnRepository, File file) {
		if (file.isModifyStatus()) {
			if (file.isFileOO()) {
				try {
					logger.info("FILE OO: " + file.getPath() + " - STATUS: modify");
					FileOO fileOO = (FileOO) file;
					CompilationUnit compilation = fileOO.buildCompilation();
					addClasses(compilation, fileOO);

					FileOO previousFileOO = (FileOO) elementDao.getPreviousFile(svnRepository, file);
					if (previousFileOO != null) {
						fileOO.markAddClasses(previousFileOO);
						fileOO.markDeletedClasses(previousFileOO);
					} else {
						logger.warn("WARN: FILE OO: " + file.getPath() + " - doesn't previous file ");
					}
					logger.info("FILE OO: " + file.getPath() + " - " + fileOO.getNumberChilds() + " classes");
				} catch (ParseException e) {
					e.printStackTrace();
					logger.error("ERROR: Obtaining compilation unit of file " + file.getPath());
				}
			} else {
				logger.info("FILE NO OO: " + file.getPath() + " - STATUS: modify");
			}
		}
	}

	private void checkDeleteFile(SVNRepository svnRepository, File file) {
		if (file.isDeleteStatus()) {
			if (file.isFileOO()) {
				logger.info("FILE OO: " + file.getPath() + " - STATUS: deleted");
				FileOO fileOO = (FileOO) file;
				FileOO previousFileOO = (FileOO) elementDao.getPreviousFile(svnRepository, file);
				if (previousFileOO != null) {
					fileOO.cloneClasses(previousFileOO, Status.DELETE);
				} else {
					logger.warn("WARN: FILE OO: " + file.getPath() + " - doesn't previous file ");
				}
				logger.info("FILE OO: " + file.getPath() + " - " + fileOO.getNumberChilds() + " classes");
			} else {
				logger.info("FILE NO OO: " + file.getPath() + " - STATUS: deleted");
			}
		}
	}

	public void setElementDao(IElementDao elementDao) {
		this.elementDao = elementDao;
	}

	public void setLoaderClass(LoaderClass loaderClass) {
		this.loaderClass = loaderClass;
	}

}